#!/usr/bin/env python
#
#
# * find is from jquery with google api, but book page is from own db. TODO: sync periodically or eventually
# * google api's weakness. TODO: appending naver result in search. author based recomendation.
# * TODO: find query logging necessary

# basic
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import util
from google.appengine.ext.webapp.util import run_wsgi_app

#json
from django.utils import simplejson
import urllib2

from xml.dom import minidom
import re

#log
import logging

#template
import os
from google.appengine.ext.webapp import template

#session
from gaesessions import get_current_session

# etc.
import datetime, time, string

#####
# DB
#####
class Reader(db.Model):
	
	uid = db.StringProperty(required=True)	# must be unique
	name = db.StringProperty() 
	time = db.DateTimeProperty(auto_now_add=True)
	bio = db.StringProperty(multiline=True)
	web = db.StringProperty()


class Book(db.Model):
	
	#
	# naver
	api_provider = db.StringProperty()
	publisher = db.StringProperty()
	time_updated = db.DateTimeProperty(auto_now_add=True)
	ISBN_13 = db.StringProperty()
	title = db.StringProperty()
	description = db.TextProperty()
	authors = db.StringListProperty()
	publishedDate = db.IntegerProperty()
	apiLink = db.LinkProperty()
	infoLink = db.LinkProperty()
	thumbnail_link = db.LinkProperty()
	
	#
	# + google 
	bookid = db.StringProperty() #unique

	country = db.StringProperty()
	ISBN_10 = db.StringProperty()
	ISBN_NOT = db.StringProperty()

	subtitle = db.StringProperty()

	categories = db.StringListProperty()
	language = db.StringProperty()
	pageCount = db.IntegerProperty()
	printType =  db.StringProperty()
	
	#publishedDate = db.DateProperty() # TODO
	#publishedDate_onlyYear = db.BooleanProperty()
	viewability = db.StringProperty()

	previewLink = db.LinkProperty()
	
	

class Like(db.Model):
	reader = db.ReferenceProperty(Reader)
	book = db.ReferenceProperty(Book)
	time = db.DateTimeProperty(auto_now_add=True)




#####
# Pages
#####
class MainPage(webapp.RequestHandler):
	def get(self):
		self.response.out.write("""
			<ul>
				<li><a href="/signup">sign up</a></li>
				<li><a href="/find">find</a></li>
			</ul>
								""")
		"""
		
			<a href="/api/quote?section=0">api/quote</a> .../api/quote?section=n means data [42*n:42*(n+1)] <br>
			<a href="/tmpwrite">tmp write</a>
		"""

class SignupPage(webapp.RequestHandler):
	def get(self):
		uid = self.request.get('uid')
		template_values = {"uid": uid}
		path = os.path.join(os.path.dirname(__file__), 'html/signup.html')
		self.response.out.write(template.render(path, template_values))

class FindPage(webapp.RequestHandler):
	def get(self):
		# TODO: find user id from device unique id
		# TODO: find recent book list to serve
		
		uid= self.request.get('uid').strip()
		session = get_current_session()
		session_uid = session.get('uid')
		
		if session_uid is None:
			session.set_quick('uid', uid)
			session_uid = session.get('uid')
		
		session = get_current_session()
		template_values = {
			
		}
		path = os.path.join(os.path.dirname(__file__), 'html/find.html')
		self.response.out.write(template.render(path, template_values))

class MeMyPage(webapp.RequestHandler):
	def get(self):
		uid= self.request.get('uid').strip()
		session = get_current_session()
		session_uid = session.get('uid')
		
		if session_uid is None:
			session.set_quick('uid', uid)
			session_uid = session.get('uid')
			
		qstr = "SELECT __key__ FROM Reader WHERE uid = '%s'" % (session_uid,)
		usr_id = db.GqlQuery(qstr).fetch(1)
		
		if usr_id:
			usr_id = usr_id[0].id()
			reader = Reader.get_by_id(usr_id)
			template_values = {
				"visit_name": reader.name,
				"session_name": reader.name,
				"bio": reader.bio,
				"web": reader.web,
				"uid": uid
			}
			path = os.path.join(os.path.dirname(__file__), 'html/me.html')
			self.response.out.write(template.render(path, template_values))
		else:
			self.redirect('/login')

"""
class MePage(webapp.RequestHandler):
	def get(self, catID, subcatID=None, prodID=None):

		session = get_current_session()
		name = session.get('name')
		
		# check validity of visit_name
		qstr = "SELECT __key__ FROM Reader WHERE name = '%s'" % (catID,)
		if not db.GqlQuery(qstr).fetch(1):
			self.redirect('/me/'+name)
			return
		
		qstr = "SELECT __key__ FROM Reader WHERE name = '%s'" % (name,)
		usr_id = db.GqlQuery(qstr).fetch(1)
		
		if usr_id:
			usr_id = usr_id[0].id()
			reader = Reader.get_by_id(usr_id)
			template_values = {
				"visit_name": catID,
				"session_name": name,
				"twitter": reader.twitter,
				"bio": reader.bio,
				"pic": reader.pic,
				"web": reader.web
			}
			path = os.path.join(os.path.dirname(__file__), 'html/me.html')
			self.response.out.write(template.render(path, template_values))
		else:
			self.redirect('login')
"""	
	
	
		
class MeEditPage(webapp.RequestHandler):
	def get(self):
		uid= self.request.get('uid').strip()
		session = get_current_session()
		session_uid = session.get('uid')
		
		if session_uid is None:
			session.set_quick('uid', uid)
			session_uid = session.get('uid')
		
		qstr = "SELECT __key__ FROM Reader WHERE uid = '%s'" % (session_uid,)
		usr_id = db.GqlQuery(qstr).fetch(1)
		
		if usr_id:
			usr_id = usr_id[0].id()
			reader = Reader.get_by_id(usr_id)
		
			template_values = {
				"name": reader.name,
				"bio": reader.bio,
				"web": reader.web
			}
			path = os.path.join(os.path.dirname(__file__), 'html/me_edit.html')
			self.response.out.write(template.render(path, template_values))
		else:
			self.redirect('/login')
		
		return

class Page42(webapp.RequestHandler):
	def get(self):
		uid= self.request.get('uid').strip()
		
		# check user info
		qstr = "SELECT * FROM Reader WHERE uid = '%s'" % (uid,)
		usr = db.GqlQuery(qstr).fetch(1)
		if not usr:
			# registration
			reader = Reader(uid = uid)
			reader.put()
			
			# session
			session = get_current_session()
			session.set_quick('uid', uid)
			session_uid = session.get('uid')
	
			template_values = {
				'name': session_uid,
				'welcome' : True
			}
			
		else:
			session = get_current_session()
			session_uid = session.get('uid')
	
			template_values = {
				'name': session_uid	
			}
			
		path = os.path.join(os.path.dirname(__file__), 'html/42.html')
		self.response.out.write(template.render(path, template_values))
		return

class LoginPage(webapp.RequestHandler):
	def get(self):
		
		path = os.path.join(os.path.dirname(__file__), 'html/login.html')
		self.response.out.write(template.render(path, ''))
		return
	
class LogoutPage(webapp.RequestHandler):
	def get(self):
		
		session = get_current_session()
		session.clear()
		
		path = os.path.join(os.path.dirname(__file__), 'html/logout.html')
		self.response.out.write(template.render(path, ''))
		return

class LikesMyPage(webapp.RequestHandler):
	def get(self):
		
		uid= self.request.get('uid').strip()
		session = get_current_session()
		session_uid = session.get('uid')

		if not session_uid:
			session.set_quick('uid', uid)
			session_uid = session.get('uid')
		
		qstr = "SELECT __key__ FROM Reader WHERE uid = '%s'" % (session_uid,)
		reader = db.GqlQuery(qstr).fetch(1)
		
		if reader:
			reader = reader[0]
			likes = Like.all().filter('reader =', reader).fetch(1000)
			
			# author name sorting
			likes = sorted(likes, key=lambda likes: likes.book.publishedDate,reverse=True)
			likes = sorted(likes, key=lambda likes: likes.book.authors)
	
			template_values = {
				'likes': likes
				}
			path = os.path.join(os.path.dirname(__file__), 'html/likes.html')
			self.response.out.write(template.render(path, template_values))
			return
		else:
			self.redirect("/login")


"""
class LikesPage(webapp.RequestHandler):
	def get(self, catID, subcatID=None, prodID=None):

		session = get_current_session()
		name = session.get('name')
		
		qstr = "SELECT __key__ FROM Reader WHERE name = '%s'" % (catID,)
		reader = db.GqlQuery(qstr).fetch(1)
		if reader.__len__():
			reader = reader[0]
		else:
			self.redirect("/likes")
		
		likes = Like.all().filter('reader =', reader).fetch(1000)
		
		# author name sorting
		likes = sorted(likes, key=lambda likes: likes.book.publishedDate,reverse=True)
		likes = sorted(likes, key=lambda likes: likes.book.authors)

		template_values = {
			'likes': likes,
			'visit_name': catID,
			'name': name
		}
		path = os.path.join(os.path.dirname(__file__), 'html/likes.html')
		self.response.out.write(template.render(path, template_values))
		return
"""

class BookPage(webapp.RequestHandler):
	def get(self, catID, subcatID=None, prodID=None):
		
		# check book in db
		qstr = "SELECT * FROM Book WHERE ISBN_13 = '%s'" % (catID,)
		book = db.GqlQuery(qstr).fetch(1)
		
		
		""" google api
		# get info from google book api
		if not book:
			
			# getting google id
			gid = self.request.get('gid')
			
			# getting info
			googleAPIKey = 'AIzaSyCSPRhfVqueRQ5KzjvRqSSHZEOmUBYv0Lc'
			req = 'https://www.googleapis.com/books/v1/volumes/' + gid + '?key=' + googleAPIKey
		
			result = urllib2.urlopen(req).read() #retrieving a specific volume
			obj = simplejson.loads(result)
			
			book = Book()
			
			book.bookid = obj.get("id")
			book.apiLink = db.Link(obj.get("selfLink"))
			book.viewability = obj["accessInfo"].get("viewability")
			book.country = obj["accessInfo"].get("country")
			
			vol = obj.get("volumeInfo")
			if vol:
				book.authors = vol.get("authors")
				book.categories = vol.get("categories")
				thumb = vol.get("imageLinks")
				if thumb:
					if thumb.get("thumbnail"):
						book.thumbnail_link = db.Link(thumb.get("thumbnail"))
					
				for i in vol.get("industryIdentifiers"):
					if i.get("type") == "ISBN_10":
						book.ISBN_10 = i.get("identifier")
					elif i["type"] == "ISBN_13":
						book.ISBN_13 = i.get("identifier")
					else:
						book.ISBN_NOT = i.get("identifier")
			
				if vol.get("infoLink") is not None:
					book.infoLink = db.Link(vol.get("infoLink"))
					
				book.language = vol.get("language")
				
				if vol.get("pageCount") is not None:
					book.pageCount = int(vol.get("pageCount"))
				
				if vol.get("previewLink") is not None:
					book.previewLink = db.Link(vol.get("previewLink"))
				
				ptime = vol.get("publishedDate")
				ptime = int(ptime[:4])
				book.publishedDate = ptime
				
				book.printType = vol.get("printType")
				book.subtitle = vol.get("subtitle")
				book.title = vol.get("title")
				book.description = vol.get("description")
			
			book.put()
			
		else:
			book = book[0]
		"""
		
		# naver api
		if not book:
			
			isbn13 = catID
			key = '81694fdfd82a615c8821bf5be3c1cc16';
			apiurl = 'http://openapi.naver.com/search?key='+key+'&query=null&target=book_adv&d_isbn='+isbn13;
			
			result = urllib2.urlopen(apiurl).read() #retrieving a specific volume
			rss= minidom.parseString(result)
			
			book = Book()
			
			book.api_provider = "naver"
			book.title = rss.getElementsByTagName("item")[0].getElementsByTagName("title")[0].childNodes[0].data
			book.infoLink = rss.getElementsByTagName("item")[0].getElementsByTagName("link")[0].childNodes[0].data
			book.publishedDate = int(rss.getElementsByTagName("item")[0].getElementsByTagName("pubdate")[0].childNodes[0].data)
			book.publisher = rss.getElementsByTagName("item")[0].getElementsByTagName("publisher")[0].childNodes[0].data
			
			try:
				book.description = rss.getElementsByTagName("item")[0].getElementsByTagName("description")[0].childNodes[0].data
			except:
				logging.info("book description error: " + isbn13)
			
			# 10 or 13 isbn
			isbn = rss.getElementsByTagName("item")[0].getElementsByTagName("isbn")[0].childNodes[0].data
			b = re.search(r"(.*)<.*>(.*)</.*>(.*)", isbn)
			if b.group(2):
				book.ISBN_13 = b.group(2).strip()
			else:
				book.ISBN_13 = rss.getElementsByTagName("item")[0].getElementsByTagName("isbn")[0].childNodes[0].data.strip()
			
			try:
				authors = rss.getElementsByTagName("item")[0].getElementsByTagName("author")[0].childNodes[0].data
				
				alist = authors.split('|')
				res = []
				for i in alist:
					i.replace("<strong>","")
					i.replace("</strong>","")
					i = i.strip()
					res.append(i)
					
				book.authors = res
			except:
				logging.info("book author error: " + isbn13)
			
			img = rss.getElementsByTagName("item")[0].getElementsByTagName("image")
			if img != []:
				book.thumbnail_link = img[0].childNodes[0].data
			
			book.put()
			
		else:
			book = book[0]
		
		bLike = False;
		
		session = get_current_session()
		session_uid = session.get('uid')
		if session_uid:
			qstr = "SELECT __key__ FROM Reader WHERE uid = '%s'" % (session_uid,)
			reader = db.GqlQuery(qstr).fetch(1)[0]
			
			like = Like.all().filter('book =', book.key()).filter('reader =', reader).fetch(1)
			if like.__len__():
				bLike = True
		
		template_values = {
			'book': book,
			'bLike': bLike
		}
		path = os.path.join(os.path.dirname(__file__), 'html/book.html')
		self.response.out.write(template.render(path, template_values))
		
#####
# Handlers
#####
class LikeHandler(webapp.RequestHandler):
	def post(self):
		session = get_current_session()
		session_uid = session.get('uid')
		
		isbn13 = self.request.get('isbn13').strip().lower()
		logging.info(isbn13)
		
		qstr = "SELECT __key__ FROM Reader WHERE uid = '%s'" % (session_uid,)
		reader = db.GqlQuery(qstr).fetch(1)[0]
		
		qstr = "SELECT __key__ FROM Book WHERE ISBN_13 = '%s'" % (isbn13,)
		book = db.GqlQuery(qstr).fetch(1)[0]
		
		like = Like.all().filter('book =', book).filter('reader =', reader).fetch(1)
		if like.__len__():
			like[0].delete()
		else:			
			like = Like()
			like.book = Book.get(book)
			like.reader = Reader.get(reader)
			like.put()
		
		return

class MeEditHandler(webapp.RequestHandler):
	def post(self):
		bio = self.request.get('bio').strip()
		web = self.request.get('web').strip()
		name = self.request.get('name').strip()
		uid = self.request.get('uid').strip()
		
		
		session = get_current_session()
		session_uid = session.get('uid')		
		
		qstr = "SELECT __key__ FROM Reader WHERE uid = '%s'" % (session_uid,)
		usr_id = db.GqlQuery(qstr).fetch(1)
		if usr_id:
			usr_id = usr_id[0].id()
			reader = Reader.get_by_id(usr_id)
			reader.name = name
			reader.bio = bio
			reader.web = web
			reader.put()
			
			self.redirect('/me?uid='+session_uid)
			
		else:
			session.set_quick('uid', uid)
			session_uid = session.get('uid')
			return
		
"""
class SignupHandler(webapp.RequestHandler):
	
	def post(self):
		name = self.request.get('name').strip().lower()
		uid= self.request.get('uid').strip().lower()
		
		# check no name and uid
		if not name and not uid: 
			self.redirect('/signup?error=noname_nouid')
			return
		elif not uid: 
			self.redirect('/signup?error=nouid')
			return
		elif not name: 
			self.redirect('/signup?error=noname&uid='+uid)
			return
		
		# check language of name
		alphas = string.letters + '_'
		nums = string.digits
		if len(name) > 2:	
			if name[0] not in alphas:
				for c in name[1:]:
					if not c in alphas+nums:
						self.redirect('/signup?error=incorrect_name&uid='+uid)
						return
		else:
			self.redirect('/signup?error=incorrect_name&uid='+uid)
			return
		
		# check validity of uid
		# TODO!
		
		# check name in db
		qstr = "SELECT * FROM Reader WHERE name = '%s'" % (name,)
		usr = db.GqlQuery(qstr).fetch(1)
		if usr:
			self.redirect('/signup?error=already_name&uid='+uid)
			return
		
		# check uid in db
		qstr = "SELECT * FROM Reader WHERE uid = '%s'" % (uid,)
		usr = db.GqlQuery(qstr).fetch(1)
		if usr:
			self.redirect('/signup?error=already_uid&uid='+uid)
			return
		
		# registration
		reader = Reader(name = name, uid = uid)
		reader.put()
		
		# session
		session = get_current_session()
		session.set_quick('name', name)

		self.redirect('/find')
			
		return
"""


def main():
	application = webapp.WSGIApplication([
											('/', 				MainPage),
										#	('/signup', 		SignupPage),
										#	('/signup_handler',	SignupHandler),
											('/find', 			FindPage),
											(r'/book/(.+)', 	BookPage),
											('/me', 			MeMyPage),
										#	(r'/me/(.+)', 		MePage),
											('/me_edit', 		MeEditPage),
											('/me_edit_handler',MeEditHandler),
											('/api/like', 		LikeHandler),
											('/likes', 			LikesMyPage),
										#	(r'/likes/(.+)', 	LikesPage),
											('/42',				Page42),
											('/login', 			LoginPage),
											('/logout', 		LogoutPage)

										], debug=True)
	util.run_wsgi_app(application)

if __name__ == '__main__':
	main()
